﻿using System;

namespace HeroldIT.Dnn.Modules
{
    /// <summary>
    /// Holds information about a related entity.
    /// </summary>
    public class RelationInfo : IEquatable<RelationInfo>
    {
        /// <summary>
        /// Gets or sets the id of the related entity.
        /// </summary>
        public Guid Id { get; set; }

        /// <summary>
        /// Gets or sets the displayed name of the related entity.
        /// </summary>
        /// <remarks>
        /// The displayed name of the entity should NOT updated, when an entity with a
        /// <see cref="RelationInfo"/> is stored. When storing, only the <see cref="Id"/>
        /// is of importance.
        /// </remarks>
        public string DisplayName { get; set; }

        /// <summary>
        /// Creates a new <see cref="RelationInfo"/> entity.
        /// </summary>
        /// <param name="id">The id of the related entity.</param>
        /// <param name="displayName">The displayed name of the related entity.</param>
        public RelationInfo(Guid id, string displayName)
        {
            this.Id = id;
            this.DisplayName = displayName;
        }

        /// <summary>
        /// Creates a new <see cref="RelationInfo"/> entity from a <see cref="Guid"/>.
        /// </summary>
        /// <param name="id">The id of the related entity.</param>
        /// <returns>A new <see cref="RelationInfo"/> entity with the given <paramref name="id"/>.</returns>
        public static implicit operator RelationInfo(Guid id)
        {
            return new RelationInfo(id, null);
        }

        /// <summary>
        /// Indicates whether the current object is equal to another object of the same type.
        /// </summary>
        /// <returns>
        /// true if the current object is equal to the other parameter; otherwise, false.
        /// </returns>
        /// <param name="other">An object to compare with this object.</param>
        public bool Equals(RelationInfo other)
        {
            if (ReferenceEquals(null, other)) return false;
            if (ReferenceEquals(this, other)) return true;
            return other.Id.Equals(this.Id);
        }

        /// <summary>
        /// Determines whether the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>.
        /// </summary>
        /// <returns>
        /// true if the specified <see cref="T:System.Object"/> is equal to the current <see cref="T:System.Object"/>; otherwise, false.
        /// </returns>
        /// <param name="obj">The <see cref="T:System.Object"/> to compare with the current <see cref="T:System.Object"/>. </param><filterpriority>2</filterpriority>
        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != typeof (RelationInfo)) return false;
            return this.Equals((RelationInfo) obj);
        }

        /// <summary>
        /// Serves as a hash function for a particular type. <see cref="M:System.Object.GetHashCode"/> is suitable for use in hashing algorithms and data structures like a hash table.
        /// </summary>
        /// <returns>
        /// A hash code for the current <see cref="T:System.Object"/>.
        /// </returns>
        /// <filterpriority>2</filterpriority>
        public override int GetHashCode()
        {
            return this.Id.GetHashCode();
        }

        /// <summary>
        /// Determines whether the specified <see cref="RelationInfo"/> instances are considered equal.
        /// </summary>
        /// <param name="left">The first <see cref="RelationInfo"/> to compare.</param>
        /// <param name="right">The second <see cref="RelationInfo"/> to compare.</param>
        /// <returns><c>true</c> if the specified <see cref="RelationInfo"/> instances are equal; otherwise, <c>false</c>.</returns>
        public static bool operator ==(RelationInfo left, RelationInfo right)
        {
            return Equals(left, right);
        }

        /// <summary>
        /// Determines whether the specified <see cref="RelationInfo"/> instances are not considered equal.
        /// </summary>
        /// <param name="left">The first <see cref="RelationInfo"/> to compare.</param>
        /// <param name="right">The second <see cref="RelationInfo"/> to compare.</param>
        /// <returns><c>true</c> if the specified <see cref="RelationInfo"/> instances are not equal; otherwise, <c>true</c>.</returns>
        public static bool operator !=(RelationInfo left, RelationInfo right)
        {
            return !Equals(left, right);
        }
    }
}